<?php
class SalesController extends AppController {
	var $name = 'Sales';
    var $memberPayExtra = 0.15;
    var $convertRate    = 4;
    var $stockDeductBy = 'confirm payment'; // order | confirm payment | ship
    var $paymentType   = array(
        'CH' => 'Cash, Check, Money Order of Fax, or offline credit card',
        'CR' => 'EWAY',
        'TL' => 'TW Eway',
        'AM' => 'AIM',
        'PR' => 'Credit Card',
        'PE' => 'EzyCash Card',
        'PA' => 'Cash',
        'PH' => 'Cheque or Money Order',
        'PM' => 'Manual Credit Card',
        'AU' => 'Authorized Trans',
        'TT' => 'T/T',
        'EP' => 'Product Account',
        'EB' => 'Buy one get one free account',
        'EA' => 'Auto-qualification Account',
        'EG' => 'Gift Certificate',
        'ER' => 'Rego Credit',
        'EV' => 'VIP bonus deduction responsible BV account',
        'CP' => 'Product Coupon',
        'PP' => 'PayPal',
        'NT' => 'NETS',
        'OT' => 'Other',
        'AT' => 'Auto BV Order'
    );
    var $paymentStatus = array(
        'E' => 'Pending',
        'P' => 'Paid',
        'X' => 'Processed',
        'D' => 'Deleted',
        'R' => 'Refund'
    );
    var $deliverMethod = array(
        'BY' => 'Delivery by company',
        'PI' => 'Self pick up',
        'UP' => 'UPS',
        'NO' => 'Standard ordinary mail',
        'EX' => 'Express mail'
    );
    var $orderStatus   = array(
        'I' => 'Pending',
        'S' => 'Shipped',
        'P' => 'Partial Shipped',
        'F' => 'Shipped(P)'
    );

    public function admin_monthly_report () {
        if ($this->RequestHandler->isAjax()) {
            $form = $this->params['form'];

            $this->set('data', $this->Sale->monthlySalesReport($form));
            $this->render('admin_month_sales_report_tbl', 'blank');
        } else {
            $this->pageTitle = __('Monthly Sales Report', true);
            $this->set('pageTitle', $this->pageTitle);
            $this->set('months', $this->_getMonthsOption());
            $this->set('fmonth', date('m', strtotime('last month')));
            $this->set('fyear', date('Y',  strtotime('last month')));
            $this->set('tmonth', date('m'));
            $this->set('tyear', date('Y'));
        }
    } // admin_monthly_report

    public function admin_order_report () {
        if ($this->RequestHandler->isAjax()) {
            $form = $this->params['form'];

            $this->set('data', $this->Sale->orderReport($form));
            $this->render('admin_order_report_tbl', 'blank');
        } else {
            $this->loadModel('Stockist');
            $data = $this->Stockist->find('list', array(
                'order' => 'name ASC'
            ));

            $this->stylesheet  = am($this->stylesheet, 'ui.daterangepicker', 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/themes/smoothness/jquery-ui.css');
            $this->javascripts = am($this->javascripts, 'http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js', 'jquery-ui-1.7.1.custom.min', 'daterangepicker', 'admin_sale_order_report');
            $this->pageTitle = __('Order Report (Offline)', true);
            $this->set('pageTitle', $this->pageTitle);
            $this->set('stockist', $data);
        }
    } // admin_order_report

    public function admin_statistic_report () {
        if ($this->RequestHandler->isAjax()) {
            $form = $this->params['form'];

            $this->set('data', $this->Sale->statisticReport($form));
            $this->render('admin_statistic_report_tbl', 'blank');
        } else {
            $this->loadModel('Stockist');
            $data = $this->Stockist->find('list', array(
                'order' => 'name ASC'
            ));

            $this->stylesheet  = am($this->stylesheet, 'ui.daterangepicker', 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/themes/smoothness/jquery-ui.css');
            $this->javascripts = am($this->javascripts, 'http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js', 'jquery-ui-1.7.1.custom.min', 'daterangepicker', 'admin_sale_statistic_report');
            $this->pageTitle = __('Statistic (Account)', true);
            $this->set('pageTitle', $this->pageTitle);
            $this->set('stockist', $data);
            $this->render('admin_reports');
        }
    } // admin_statistic_report

    public function admin_inventory_report () {
        if ($this->RequestHandler->isAjax()) {
            $form = $this->params['form'];

            $this->set('data', $this->Sale->inventorySalesReport($form));
            $this->render('admin_inventory_report_tbl', 'blank');
        } else {
            $this->loadModel('Stockist');
            $data = $this->Stockist->find('list', array(
                'order' => 'name ASC'
            ));

            $this->stylesheet  = am($this->stylesheet, 'ui.daterangepicker', 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/themes/smoothness/jquery-ui.css');
            $this->javascripts = am($this->javascripts, 'http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js', 'jquery-ui-1.7.1.custom.min', 'daterangepicker', 'admin_sale_inventory_report');
            $this->pageTitle = __('Inventory Sales Report', true);
            $this->set('pageTitle', $this->pageTitle);
            $this->set('stockist', $data);
            $this->render('admin_reports');
        }
    } // admin_inventory_report

    public function admin_weekly_bonus_report () {
        if ($this->RequestHandler->isAjax()) {
            $form = $this->params['form'];

            $this->loadModel('MemberCashSales');
            $this->set('data', $this->MemberCashSales->weeklyBonusReport($form));
            $this->render('admin_weekly_bonus_report_tbl', 'blank');
        } else {
            $this->loadModel('Stockist');
            $data = $this->Stockist->find('list', array(
                'order' => 'name ASC'
            ));

            $this->stylesheet  = am($this->stylesheet, 'ui.daterangepicker', 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/themes/smoothness/jquery-ui.css');
            $this->javascripts = am($this->javascripts, 'http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js', 'jquery-ui-1.7.1.custom.min', 'daterangepicker', 'sales/admin_weekly_bonus_report');
            $this->pageTitle = __('Weekly Bonus Report', true);
            $this->set('pageTitle', $this->pageTitle);
            $this->set('stockist', $data);
            $this->render('admin_reports');
        }
    } // admin_weekly_bonus_report

    public function admin_top_bv_purchase_report () {
        if ($this->RequestHandler->isAjax()) {
            $form = $this->params['form'];

            $this->set('data', $this->Sale->topBvPurchaseReport($form));
            $this->render('admin_top_bv_purchase_report_tbl', 'blank');
        } else {
            $this->loadModel('Stockist');
            $data = $this->Stockist->find('list', array(
                'order' => 'name ASC'
            ));

            $this->stylesheet  = am($this->stylesheet, 'ui.daterangepicker', 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/themes/smoothness/jquery-ui.css');
            $this->javascripts = am($this->javascripts, 'http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js', 'jquery-ui-1.7.1.custom.min', 'daterangepicker', 'admin_sale_top_bv_purchase_report');
            $this->pageTitle = __('Top BV Purchase Report', true);
            $this->set('pageTitle', $this->pageTitle);
            $this->set('stockist', $data);
            $this->render('admin_reports');
        }
    } // admin_top_bv_purchase_report

    public function admin_1st_gen_sponsored_bv_report () {
        if ($this->RequestHandler->isAjax()) {
            $form = $this->params['form'];

            $this->set('data', $this->Sale->firstGenSponsoredBvReport($form));
            $this->render('admin_1st_gen_sponsored_bv_report_tbl', 'blank');
        } else {
            $this->loadModel('Stockist');
            $data = $this->Stockist->find('list', array(
                'order' => 'name ASC'
            ));

            $this->stylesheet  = am($this->stylesheet, 'ui.daterangepicker', 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/themes/smoothness/jquery-ui.css');
            $this->javascripts = am($this->javascripts, 'http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js', 'jquery-ui-1.7.1.custom.min', 'daterangepicker', 'admin_sale_1st_gen_sponsored_bv_report');
            $this->pageTitle = __('1st Generation Sponsored BV Report', true);
            $this->set('pageTitle', $this->pageTitle);
            $this->set('stockist', $data);
            $this->render('admin_reports');
        }
    } // admin_1st_gen_sponsored_bv_report

    public function admin_top_sales_report () {
        if ($this->RequestHandler->isAjax()) {
            $form = $this->params['form'];

            $this->set('data', $this->Sale->topSalesReport($form));
            $this->render('admin_top_sales_report_tbl', 'blank');
        } else {
            $this->loadModel('Stockist');
            $data = $this->Stockist->find('list', array(
                'order' => 'name ASC'
            ));

            $this->stylesheet  = am($this->stylesheet, 'ui.daterangepicker', 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/themes/smoothness/jquery-ui.css');
            $this->javascripts = am($this->javascripts, 'http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js', 'jquery-ui-1.7.1.custom.min', 'daterangepicker', 'sales/admin_top_sales_report');
            $this->pageTitle = __('Top Sales Report', true);
            $this->set('pageTitle', $this->pageTitle);
            $this->set('stockist', $data);
            $this->render('admin_reports');
        }
    } // admin_top_sales_report

    public function admin_new_member_club_report () {
        if ($this->RequestHandler->isAjax()) {
            $this->loadModel('MemberCashSales');
            $this->loadModel('Member');

            $form = $this->params['form'];
            $data = $this->MemberCashSales->newMemberClubReport($form);

            if (count($data) > 0) {
                $code = array_keys($data);
                $memb = $this->Member->find('all', array(
                    'conditions' => array('Member.international_id' => $code),
                    'recursive'  => -1,
                    'fields'     => 'id, international_id, fullname, country, mobile'
                ));
                foreach ($memb as $m) {
                    $c = $m['Member']['international_id'];

                    $data[$c]['id']       = $m['Member']['id'];
                    $data[$c]['fullname'] = $m['Member']['fullname'];
                    $data[$c]['country']  = $m['Member']['country'];
                    $data[$c]['mobile']   = $m['Member']['mobile'];
                }
            }

            $this->set('data', $data);
            $this->render('admin_new_member_club_report_tbl', 'blank');
        } else {
            $this->pageTitle = __('New Member Club Report', true);
            $this->set('pageTitle', $this->pageTitle);
            $this->set('months', $this->_getMonthsOption());
            $this->set('month', date('m'));
            $this->set('year', date('Y'));
        }
    } // admin_new_member_club_report

    public function admin_payout_report () {
        if ($this->RequestHandler->isAjax()) {
            $this->loadModel('MemberCashSales');
            $this->loadModel('Member');

            if (empty($this->params['form']['country'])) {
                $this->params['form']['country'] = 'Malaysia';
            }

            $form = $this->params['form'];
            $data = $this->MemberCashSales->payoutReport($form);

            if (isset($data['list']) && count($data['list']) > 0) {
                $code = array_keys($data['list']);
                $memb = $this->Member->find('all', array(
                    'conditions' => array('Member.international_id' => $code),
                    //'conditions' => array('Member.country' => $form['country']),
                    'recursive'  => -1,
                    'fields'     => 'id, international_id, fullname, country, mobile'
                ));
                foreach ($memb as $m) {
                    $c = $m['Member']['international_id'];

                    $data['list'][$c]['id']       = $m['Member']['id'];
                    $data['list'][$c]['fullname'] = $m['Member']['fullname'];
                    $data['list'][$c]['country']  = $m['Member']['country'];
                    $data['list'][$c]['mobile']   = $m['Member']['mobile'];
                }
            }

            $this->set('data', $data);
            $this->render('admin_payout_report_tbl', 'blank');
        } else {
            $this->pageTitle = __('Payout Report', true);
            $this->set('pageTitle', $this->pageTitle);
            $this->set('months', $this->_getMonthsOption());
            $this->set('month', date('m'));
            $this->set('year', date('Y'));
        }
    } // admin_payout_report

    public function admin_bonus_payout_report () {
        if ($this->RequestHandler->isAjax()) {
            $this->loadModel('MemberCashSales');
            $this->loadModel('Member');

            if (empty($this->params['form']['country'])) {
                $this->params['form']['country'] = 'Malaysia';
            }

            $form = $this->params['form'];
            $resp = $this->MemberCashSales->bonusPayoutReport($form);
            $data = $temp = array();

            if (count($resp) > 0 && $resp != 0) {
                $code = array_keys($resp);
                $memb = $this->Member->find('all', array(
                    'conditions' => array(
                        'Member.international_id' => $code,
                        'Member.transfer_bank'    => 1
                    ),
                    'recursive'  => -1,
                    'fields'     => 'international_id, fullname, identity, branch, bank_account'
                ));

                foreach ($memb as $m) {
                    $c = $m['Member']['international_id'];

                    $data[$c]['fullname'] = $m['Member']['fullname'];
                    $data[$c]['identity'] = $m['Member']['identity'];
                    $data[$c]['acc_no']   = $m['Member']['bank_account'];
                    $data[$c]['bankname'] = $m['Member']['branch'];

                    $data[$c] = array_merge($resp[$c], $data[$c]);
                }
                foreach ($data as $m) {
                    $temp[] = isset($m['fullname']) ? $m['fullname'] : '';
                }
                array_multisort($temp, $data);
            }

            $list = array('No,Name,Account No,Receiving Bank,IC No. (not populated),,Disbursed Amount (RM),,,,');
            $fp   = fopen(WWW_ROOT.'files'.DS.'bonus_payout.csv', 'w');
            $i    = 0;

            foreach ($data as $r) {
                if (isset($r['fullname'])) {
                    $i++;
                    $list[] = $i.','.$r['fullname'].','.$r['acc_no'].','.$r['bankname'].','.$r['identity'].',,'.$r['total'].',,,,';
                }
            }
            foreach ($list as $line) {
                fputcsv($fp, split(',', $line));
            }
            fclose($fp);

            $this->set('data', $data);
            $this->render('admin_bonus_payout_report_tbl', 'blank');
        } else {
            $this->pageTitle = __('Bonus Payout Report', true);
            $this->set('pageTitle', $this->pageTitle);
            $this->set('months', $this->_getMonthsOption());
            $this->set('month', date('m'));
            $this->set('year', date('Y'));
        }
    } // admin_bonus_payout_report

    public function admin_listData ($type=null) {
        $rs = $this->Sale->listing($this->params['form'], array(
            'paymentType'   => $this->paymentType,
            'paymentStatus' => $this->paymentStatus,
            'deliverMethod' => $this->deliverMethod,
            'orderStatus'   => $this->orderStatus
        ));

        $json = ($rs) ? $rs : array(
            'page'  => 1,
            'total' => 0,
            'rows'  => array()
        );

        $this->response($json);
    } // admin_listData

    public function admin_update () {
        $data   = $this->params['form'];
        $amount = $bv = 0;
        $items  = $inventory = $deduct = $stocks = array();


        $this->loadModel('Member');
        $member = $this->Member->find('first', array(
            'conditions' => array('international_id' => $data['member_code']),
            'recursive'  => -1,
            'fields'     => 'id, rank_id'
        ));

        if (empty($member['Member']['id'])) {
            $json = array(
                'status' => false,
                'mesg'   => __('User Id ['.$data['member_code'].'] does not found in database', true),
                'error'  => array(
                    array('id'=>'member-code', 'field'=>'member-code', 'code'=>'Invalid user id')
                )
            );
            $this->response($json);
            return;
        }

        $sale_date   = $this->clientToServerTime($data['date'].' '.$data['time']);
        $rank_id     = $this->Sale->userRank($member['Member']['id']);
        $stockist_id = empty($data['stockist_id']) ? 1 : $data['stockist_id'];

        foreach ($data as $f=>$v) {
            if (substr($f, 0, 2) == 'p_' && $v) { // list of order items filter by prefix 'P_'
                $this->loadModel('Product');

                $id = substr($f, 2);
                $p  = $this->Product->read(array('code','bv','cost','price','include_ids'), $id);

                if (isset($p['Product']['code'])) {
                    $price   = ($rank_id == 1) ? ($p['Product']['price'] * (1 + $this->memberPayExtra)) : $p['Product']['price']; // normal member price charge 15% higher
                    $amount += $price * $v;
                    $bv     += $p['Product']['bv'] * $v;

                    $items[] = array(
                        'product_id'   => $id,
                        'product_code' => $p['Product']['code'],
                        'quantity'     => $v,
                        'bv'           => $p['Product']['bv'],
                        'price'        => $price
                        //'locate_price' => $price * $this->convertRate
                    );

                    if ($p['Product']['include_ids']) { // it's package, find its product id
                        $products = $this->Product->getInfoByCode($p['Product']['include_ids']);

                        if (is_array($products)) {
                            foreach ($products as $pd) {
                                $inventory[] = array(
                                    'product_id'   => $pd['id'],
                                    'product_code' => $pd['code'],
                                    'quantity'     => $v,
                                    'cost'         => $pd['cost']
                                );

                                if ($this->stockDeductBy == 'order') {  // should Stock deducted instantly when Order has made?
                                    $deduct[$pd['id']] = $v;
                                }
                            }
                        }
                    } else { // normal item, just use product id
                        $inventory[] = array(
                            'product_id'   => $id,
                            'product_code' => $p['Product']['code'],
                            'quantity'     => $v,
                            'cost'         => $p['Product']['cost']
                        );

                        if ($this->stockDeductBy == 'order') {
                            $deduct[$id] = $v;
                        }
                    }
                }
            }
        }

        $buyCoupon = $couponNo = null;
        $useCoupon = 'N';
        $couponTtl = $balance = 0;

        if (isset($data['coupon_id']) && isset($data['useCoupon']) && $data['useCoupon'] == 'Y') { // sales is purchase with coupon
            $coupon = $this->_couponPurchase($data['coupon_id']);

            if (is_array($coupon)) {
                $useCoupon = 'Y';
                $couponNo  = $coupon['doc_no'];
                $couponTtl = $coupon['total'];
                $balance   = $coupon['balance'] - $amount; // balance of coupon value
                $amount    = $amount - $coupon['balance']; // remainig amount need to pay after deduct coupon value
                $bv        = 0;

                if ($amount < 0) {
                    $amount = 0;
                }
                if ($coupon['new']) {
                    $buyCoupon = 100;
                }
            }
        }

        $this->data['Sale'] = array(
            'member_id'        => $member['Member']['id'],
            'stockist_id'      => $stockist_id,
            'sales_date'       => $sale_date,
            'payment_type'     => $data['payment_type'],
            'payment_status'   => 'E', //$data['payment_status'],
            'order_status'     => 'I', //$data['order_status'],
            'delivery_method'  => $data['delivery_method'],
            'amount'           => $amount,
            'amount_converted' => ($amount * $this->convertRate),
            'buy_coupon'       => $buyCoupon,
            'use_coupon'       => $useCoupon,
            'rank_id'          => $rank_id,
            'total_pv'         => $bv,
            'remark'           => $data['remark']
        );

        $this->Sale->set($this->data);

        if ($this->Sale->validates()) { // data validated!
            if ($this->Sale->save($this->data)) { // save new order (MySQL)
                foreach ($items as $i=>$d) {
                    $items[$i]['sale_id'] = $this->Sale->id;
                }
                $this->loadModel('SaleItem');
                $this->SaleItem->saveAll($items, array(
                    'validate' => 'first',
                    'atomic'   => true
                )); // save order items detail

                foreach ($inventory as $i=>$d) {
                    $inventory[$i]['sale_id'] = $this->Sale->id;
                }
                $this->loadModel('SaleInventory');
                $this->SaleInventory->saveAll($inventory, array(
                    'validate' => 'first',
                    'atomic'   => true
                )); // save sales inventory detail

                if ($useCoupon == 'Y') { // insert coupon transaction to database if use
                    $this->data2['CouponHistory'] = array(
                        'member_id' => $member['Member']['id'],
                        'sale_id'   => $this->Sale->id,
                        'coupon_id' => $data['coupon_id'],
                        'coupon_no' => $couponNo,
                        'total'     => $couponTtl,
                        'balance'   => ($balance <= 0) ? 0 : $balance,
                    );

                    $this->CouponHistory->set($this->data2);

                    if ($this->CouponHistory->validates()) {
                        $this->CouponHistory->save($this->data2);
                    }
                }


                foreach ($deduct as $id=>$qty) {
                    $qty_out  = $qty - ($qty*2);
                    $stocks[] = array(
                        'stockist_id' => $stockist_id,
                        'product_id'  => $id,
                        'sale_id'     => $this->Sale->id,
                        'type'        => 'SA',
                        'datetime'    => $sale_date,
                        'in_out'      => $qty_out,
                        'remark'      => 'Sale id: '.$this->Sale->id
                    );
                }
                if (count($stocks) > 0) {
                    $this->loadModel('Stock');
                    $this->Stock->saveAll($stocks, array(
                        'validate' => 'first',
                        'atomic'   => true
                    )); // deduct stock from inventory
                }

                $json = array(
                    'status' => true,
                    'mesg'   => __('New Sales has been created successfully!',true)
                );
            } else {
                $mesg = __('Fail insert record to database at this time, please try again.',true);
                $err  = isset($this->error) ? $this->error : $mesg;
                $json = array(
                    'status' => false,
                    'mesg'   => $err
                );
            }
        } else { // invalid data found
            $json = array(
                'status' => false,
                'mesg'   => __('Please enter the requested details in the fields pointed out below and try again!', true)
            );
            foreach ($this->Stockist->invalidFields() as $k=>$v) {
                $json['error'][] = array('id'=>$k, 'field'=>$k, 'code'=>$v);
            }
        }

        $this->response($json);
    } // admin_update

    public function admin_update_status () {
        $form = $this->params['form'];

        if (!empty($form['date']) && !empty($form['time'])) {
            $updateOn = $this->clientToServerTime($form['date'].' '.$form['time']);
        } else if ($form['task'] == 'refund' || $form['task'] == 'confirm payment' || $form['task'] == 'ship order') {
            $json = array(
                'status' => false,
                'error'  => __('Required date and time missing.', true)
            );
            $this->response($json);
            return;
        }

        if ($form['task'] == 'refund') { // REFUND
            $fields = array(
                'refund_date' => "'".$updateOn."'"
            );
            $action = 'refund';
        } else if ($form['task'] == 'delete') { // DELETE
            $action = 'delete';
        } else if ($form['task'] == 'confirm payment') { // CONFIRM PAYMENT
            $fields = array(
                'confirm_date'   => "'".$updateOn."'",
                'payment_status' => "'X'"
            );
            $action = 'confirm payment';
        } else if ($form['task'] == 'ship order') { // SHIP ORDER
            $fields = array(
                'shipping_date' => "'".$updateOn."'",
                'order_status'  => "'S'"
            );
            $action = 'ship';
        } else { // UNKNOWN
            $json = array(
                'status' => false,
                'error'  => __('Process failure, missing required data.', true)
            );
            $this->response($json);
            return;
        }

        if (empty($form['id'])) {
            $json = array(
                'status' => false,
                'error'  => 'Couldn\'t '.$action.' order, missing required record Id.'
            );
            $this->response($json);
            return;
        }

        $ids = explode(',', $form['id']);

        $data = $this->Sale->find('all', array(
            'conditions' => array('Sale.id' => $ids),
            'recursive'  => -1,
            'fields'     => 'id, payment_status, order_status',
            'order'      => 'Sale.id ASC'
        )); // retrieve current payment and order status first
        $paymentStatus = $orderStatus = array();
        foreach ($data as $s) {
            $si                 = $s['Sale']['id'];
            $paymentStatus[$si] = $s['Sale']['payment_status'];
            $orderStatus[$si]   = $s['Sale']['order_status'];
        }

        if ($action == 'ship') { // need confirm payment before it can ship purchased items
            $tmp = $ign = array();
            foreach ($ids as $id) {
                if (isset($paymentStatus[$id]) && $paymentStatus[$id] == 'X') {
                    $tmp[] = $id;
                } else {
                    $ign[] = $id;
                }
            }
            $ids = $tmp;
        } else if ($action == 'confirm payment') { // no way to confirm sale that has been deleted
            $tmp = $ign = array();
            foreach ($ids as $id) {
                if (isset($paymentStatus[$id]) && $paymentStatus[$id] == 'D') {
                    $ign[] = $id;
                } else {
                    $tmp[] = $id;
                }
            }
            $ids = $tmp;
        }


        if (isset($fields) && count($fields) > 0) {
            $rs = $this->Sale->updateAll(
                $fields,
                array('Sale.id' => $ids)
            ); // update the changeds status
        } else {
            $rs = true;
        }


        if ($rs) {
            if ($action == 'ship' && $this->stockDeductBy == 'ship') { // deduct stock when purchased items mark as ship status
                foreach ($ids as $id) {
                    if (isset($paymentStatus[$id]) && ($paymentStatus[$id] == 'S' || $paymentStatus[$id] == 'F')) { // skip confirmed order
                        continue;
                    }
                    $this->_deductStockFromSales($id);
                }
            } else if ($action == 'confirm payment') { // insert validated sales to MsSQL and update member BV
                foreach ($ids as $id) {
                    if (isset($paymentStatus[$id]) && ($paymentStatus[$id] == 'X' || $paymentStatus[$id] == 'D')) { // skip confirmed order
                        continue;
                    }

                    $this->_confirmPayment($id);

                    if ($this->stockDeductBy == 'confirm payment') { // deduct stock when purchased items mark as confirm payment status
                        $this->_deductStockFromSales($id);
                    }
                }
            } else if ($action == 'delete') { // mark sales as deleted and remmove all its related records from DB
                foreach ($ids as $id) {
                    $this->_deleteSalesOrder($id);
                }
            }  else if ($action == 'refund') {
                foreach ($ids as $id) {
                    $this->_refundSalesOrder($id);
                }
            }

            if (isset($ign) && count($ign) > 0) {
                $ignored_ids = implode(', ', $ign);
                if ($action == 'ship') {
                    $subMessage = '<br />Can not ship Order Id ['.$ignored_ids.'] due to payment not confirmed.';
                } else if ($action == 'confirm payment') {
                    $subMessage = '<br />Can not confirm payment of Order Id ['.$ignored_ids.'] that have been deleted.';
                }
            } else {
                $subMessage = '';
            }

            $json = array(
                'status' => true,
                'mesg'   => __('Selected records have been updated successfully!'.$subMessage, true)
            );
        } else {
            $json = array(
                'status' => false,
                'error'  => 'Fail to '.$action.' order at this time.'
            );
        }

        $this->response($json);
    } // admin_update_status

    public function admin_manage () {
        $this->loadModel('Stockist');
        $list = $this->Stockist->find('list', array(
            'order' => 'name ASC'
        ));

        $this->stylesheet  = am($this->stylesheet, 'flexigrid/flexigrid', 'jscal2/jscal2', 'jscal2/border-radius', 'clockpick', 'popup');
        $this->javascripts = am($this->javascripts, 'http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js', 'flexigrid.min', 'jscal2', 'clockpick.min', 'admin_sale_manage');
        $this->pageTitle   = __('Order Management', true);

        $this->set('pageTitle', $this->pageTitle);
        $this->set('stockists', $list);
        $this->_populateOptions();
    } // admin_manage

    public function admin_get ($id) {
        $this->data = $this->Sale->findById($id);

        if (empty($this->data['Sale'])) {
            $json = array(
                'status' => false,
                'mesg'   => __('No data found from database', true)
            );
        }

        $data = array();
        $i    = 0;
        foreach ($this->data['Sale'] as $f=>$v) {
            $data[$i] = array(
                'f' => $f,
                'v' => $v
            );

            if ($f == 'member_id' && $v) {
                $i++;
                $this->loadModel('Member');
                $this->Member->id = $v;
                $data[$i] = array(
                    'f' => 'fullname',
                    'v' => $this->Member->field('fullname')
                );
            }/* else if ($f == 'stockist_id' && $v) {
                $i++;
                $this->loadModel('Stockist');
                $this->Stockist->id = $v;
                $data[$i] = array(
                    'f' => 'stockist',
                    'v' => $this->Stockist->field('name')
                );
            }*/

            $i++;
        }

        $this->loadModel('SaleItem');
        $data[$i] = array(
            'f' => 'order_content',
            'v' => @implode('<br /><br />', $this->SaleItem->orderList($id))
        );


        $json = array(
            'status' => true,
            'data'   => $data
        );

        $this->response($json);
    } // admin_get

    public function admin_index ($id=null) {
        $this->loadModel('Product');
        $data = $this->Product->find('all', array(
            'conditions' => 'status="A"',
            'recursive'  => -1,
            'order'      => 'include_ids ASC, code ASC'
        ));

        $this->loadModel('Stockist');
        $stokist = $this->Stockist->find('list', array(
            'recursive' => -1,
            'order'     => array('Stockist.id')
        ));


        $this->stylesheet  = am($this->stylesheet, 'autocomplete', 'jscal2/jscal2', 'jscal2/border-radius', 'clockpick');
        $this->javascripts = am($this->javascripts, 'http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js', 'autocomplete.min', 'jscal2', 'clockpick.min', 'sales/admin_sale');
        $this->pageTitle   = __('Point of Sales', true);

        $this->set('pageTitle', $this->pageTitle);
        $this->set('data', $data);
        $this->set('stokist', $stokist);
        $this->set('memberRate', $this->memberPayExtra+1);
        $this->_populateOptions();
    } // admin_index

    public function bonus_list () {
        if (!$this->_checkLogged()) {
            return;
        }

        if ($this->RequestHandler->isAjax()) {
            $this->loadModel('WeeklyBonus');

            $id   = $this->Session->read('Member.id');
            $rs   = $this->WeeklyBonus->bonusList($this->params['form'], $id);
            $json = ($rs) ? $rs : array(
                'page'  => 1,
                'total' => 0,
                'rows'  => array()
            );

            $this->response($json);
        } else {
            $this->stylesheet  = am($this->stylesheet, 'flexigrid/flexigrid');
            $this->javascripts = am($this->javascripts, 'http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js', 'flexigrid.min', 'sales/bonus_list');
            $this->pageTitle   = __('Bonus List', true);

            $this->set('pageTitle', $this->pageTitle);
        }
    } // bonus_list

    public function order_list () {
        if (!$this->_checkLogged()) {
            return;
        }

        if ($this->RequestHandler->isAjax()) {
            $id = $this->Session->read('Member.id');
            $rs = $this->Sale->saleList($this->params['form'], array(
                'paymentType'   => $this->paymentType,
                'paymentStatus' => $this->paymentStatus,
                'deliverMethod' => $this->deliverMethod,
                'orderStatus'   => $this->orderStatus
            ), $id);

            $json = ($rs) ? $rs : array(
                'page'  => 1,
                'total' => 0,
                'rows'  => array()
            );

            $this->response($json);
        } else {
            $this->stylesheet  = am($this->stylesheet, 'flexigrid/flexigrid');
            $this->javascripts = am($this->javascripts, 'http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js', 'flexigrid.min', 'sales/order_list');
            $this->pageTitle   = __('Order List', true);

            $this->set('pageTitle', $this->pageTitle);
        }
    } // order_list

    public function bv_allocation ($ax='') {
        if (!$this->_checkLogged()) {
            return;
        }

        if ($ax || $this->RequestHandler->isAjax()) {
            $id = $this->Session->read('Member.id');

            $this->loadModel('WeeklyBonus');
            $data = 0;//$this->WeeklyBonus->bvAllocation($id, $this->params['form']['side']);

            $this->set('data', $data);
            $this->render('bv_allocation_tbl', 'blank');
        } else {
            $this->javascripts = am($this->javascripts, 'sales/bv_allocation');
            $this->pageTitle   = __('BV Allowcation Check', true);

            $this->set('pageTitle', $this->pageTitle);
        }
    } // bv_allocation


    private function _populateOptions () {
        $this->set('paymentType', $this->paymentType);
        $this->set('paymentStatus', $this->paymentStatus);
        $this->set('deliverMethod', $this->deliverMethod);
        $this->set('orderStatus', $this->orderStatus);
    } // _populateOptions

    private function _couponPurchase ($id) {
        $this->loadModel('CouponHistory');

        $respon = false;
        $coupon = $this->CouponHistory->find('first', array(
            'conditions' => 'coupon_id='.$id,
            'recursive'  => -1,
            'fields'     => 'coupon_no, total, balance',
            'order'      => 'id DESC'
        ));

        if ($coupon != false) {
            $respon = array(
                'new'     => false,
                'doc_no'  => $coupon['CouponHistory']['coupon_no'],
                'total'   => $coupon['CouponHistory']['total'],
                'balance' => $coupon['CouponHistory']['balance']
            );
        } else {
            $this->loadModel('PiVoucherDetail');
            $coupon = $this->PiVoucherDetail->find('first', array(
                'conditions' => 'piVoucherHeaderID='.$id,
                'recursive'  => -1,
                'fields'     => 'documentno, Debit',
                'order'      => 'piVoucherHeaderID DESC'
            ));

            if ($coupon != false) {
                $respon = array(
                    'new'     => true,
                    'doc_no'  => $coupon['PiVoucherDetail']['documentno'],
                    'total'   => $coupon['PiVoucherDetail']['Debit'],
                    'balance' => $coupon['PiVoucherDetail']['Debit']
                );
            }
        }

        return $respon;
    } // _couponPurchase

    private function _confirmPayment ($id) { // E/P -> X
        $this->loadModel('Member');
        $this->loadModel('MemberCashSales');

        $sales = $this->Sale->read(array('member_id', 'stockist_id', 'sales_date', 'amount', 'rank_id', 'total_pv', 'created'), $id);

        $data = array(
            'MemberCashSales' => array(
                'MemberCashSaleID' => $id,
                'MembershipID'     => $sales['Sale']['member_id'],
                'StockistID'       => $sales['Sale']['stockist_id'],
                'SalesDate'        => $sales['Sale']['sales_date'],
                'InvoiceNo'        => $id,
                'RankId'           => $sales['Sale']['rank_id'],
                'TotalPV'          => $sales['Sale']['total_pv'],
                'TotalDP'          => $sales['Sale']['amount'],
                'CreateDate'       => $sales['Sale']['created']
            )
        );

        $this->MemberCashSales->save($data); // save new order (MsSQL)
        $this->Member->updateBv($sales['Sale']['member_id'], $sales['Sale']['total_pv']); // update member BV


        $this->Member->id = $sales['Sale']['member_id'];
        $join_member_date = $this->Member->field('join_date');
        $join_member_date = substr($join_member_date, 0, 7);
        $buy_confirm_date = substr($sales['Sale']['created'], 0, 7);

        if ($join_member_date == $buy_confirm_date) { // Medal calculate only in the same month of join member
            $count = $this->Sale->find('count', array(
                'conditions' => array(
                    'Sale.member_id ='       => $sales['Sale']['member_id'],
                    'Sale.payment_status ='  => 'X',
                    'Sale.confirm_date LIKE' => $join_member_date.'%'
                )
            ));

            $bv = 0;
            if ($count == 1) { // first order
                $bv = $sales['Sale']['total_pv'];
            } else { // upgrade order after buy for first time
                $bv = $this->Sale->upgradeOrderBv($sales['Sale']['member_id'], $join_member_date);
            }
            if ($bv) {
                if ($bv >= 280) { // get GOLD medal
                    $medal = 1;
                } else if ($bv >= 140) { // get SILVER medal
                    $medal = 2;
                } else { // get BROWN medal
                    $medal = 3;
                }

                $this->Member->id = $sales['Sale']['member_id'];
                $this->Member->saveField('medal', $medal);
            }
        }

        return true;
    } // _confirmPayment

    private function _undoConfirmPayment ($id, $status) { // X -> E/P
        $this->loadModel('Member');
        $this->loadModel('MemberCashSales');

        $sales = $this->Sale->read(null, $id);
        if ($sales['Sale']['payment_status'] == 'X') {
            $bv = $sales['Sale']['total_pv'];
            $bv = $bv - ($bv*2);
            $this->Member->updateBv($sales['Sale']['member_id'], $bv); // deduct BV back from confirmed payment
        }
        $this->Sale->set(array(
            'confirm_date'   => null,
            'payment_status' => $status
        ));
        $this->Sale->save();

        $this->MemberCashSales->deleteAll(array('MemberCashSaleID'=>$id));

        return true;
    } // _undoConfirmPayment

    private function _deductStockFromSales ($id) { // E/P -> X | I -> S/F
        $this->loadModel('SaleInventory');
        $this->loadModel('Stock');

        $stocks = array();
        $data   = $this->SaleInventory->orderStockDetails($id);

        if (count($data) == 0) {
            return 0;
        }

        $sales = $this->Sale->read(array('stockist_id', 'sales_date'), $id);

        foreach ($data as $inv) {
            $qty     = $inv['quantity'];
            $qty_out = $qty - ($qty*2);

            $stocks[] = array(
                'stockist_id' => $sales['Sale']['stockist_id'],
                'product_id'  => $inv['product_id'],
                'sale_id'     => $id,
                'type'        => 'SA',
                'datetime'    => $sales['Sale']['sales_date'],
                'in_out'      => $qty_out,
                'remark'      => 'Sale id: '.$id
            );
        }
        if (count($stocks) > 0) {
            $this->Stock->saveAll($stocks, array(
                'validate' => 'first',
                'atomic'   => true
            )); // deduct stock from inventory
        }

        return true;
    } // _deductStockFromSales

    private function _refundSalesOrder ($id) { // X -> R
        $this->loadModel('SaleInventory');
        $this->loadModel('Stock');
        $this->loadModel('Member');
        $this->loadModel('MemberCashSales');

        $sales = $this->Sale->read(null, $id);
        if ($sales['Sale']['payment_status'] == 'X') {
            $bv = $sales['Sale']['total_pv'];
            $bv = $bv - ($bv*2);
            $this->Member->updateBv($sales['Sale']['member_id'], $bv); // deduct BV back from confirmed payment
            $this->Member->addRefundTimes($sales['Sale']['member_id']); // log number of times member has refund
            $this->MemberCashSales->deleteAll(array('MemberCashSaleID'=>$id));
        }
        $this->Sale->set('payment_status', 'R');
        $this->Sale->save();


        $stocks = array();
        $data   = $this->SaleInventory->orderStockDetails($id);

        if (count($data) == 0) {
            return 0;
        }

        foreach ($data as $inv) {
            $qty_in = $inv['quantity'];

            $stocks[] = array(
                'stockist_id' => $sales['Sale']['stockist_id'],
                'product_id'  => $inv['product_id'],
                'sale_id'     => $id,
                'type'        => 'SR',
                'datetime'    => date('Y-m-d H:i:s'),
                'in_out'      => $qty_in,
                'remark'      => 'Sale id: '.$id
            );
        }
        if (count($stocks) > 0) {
            $this->Stock->saveAll($stocks, array(
                'validate' => 'first',
                'atomic'   => true
            )); // deduct stock from inventory
        }

        return true;
    } // _refundSalesOrder

    private function _deleteSalesOrder ($id) {
        $this->loadModel('SaleItem');
        $this->loadModel('SaleInventory');
        $this->loadModel('Stock');
        $this->loadModel('Member');
        $this->loadModel('MemberCashSales');

        $sales = $this->Sale->read(null, $id);
        if ($sales['Sale']['payment_status'] == 'X') {
            $bv = $sales['Sale']['total_pv'];
            $bv = $bv - ($bv*2);
            $this->Member->updateBv($sales['Sale']['member_id'], $bv); // deduct BV back from confirmed payment
        }
        $this->Sale->set('payment_status', 'D');
        $this->Sale->save();

        $this->SaleItem->deleteAll('sale_id='.$id);
        $this->SaleInventory->deleteAll('sale_id='.$id);
        $this->Stock->deleteAll('sale_id='.$id);
        $this->MemberCashSales->deleteAll(array('MemberCashSaleID'=>$id));
    } // _deleteSalesOrder

    private function _getMonthsOption () {
        return array(
                '01' => __('January',true),
                '02' => __('February',true),
                '03' => __('March',true),
                '04' => __('April',true),
                '05' => __('May',true),
                '06' => __('June',true),
                '07' => __('July',true),
                '08' => __('August',true),
                '09' => __('September',true),
                '10' => __('October',true),
                '11' => __('November',true),
                '12' => __('December',true)
            );
    } // _getMonthsOption
} // SalesController
?>